package com.ncepu.clubmanagement.service.impl;

import com.github.pagehelper.util.StringUtil;
import com.ncepu.clubmanagement.anno.CommitteePermission;
import com.ncepu.clubmanagement.exception.AlreadyExistException;
import com.ncepu.clubmanagement.exception.NotExistException;
import com.ncepu.clubmanagement.mapper.AffairsMapper;
import com.ncepu.clubmanagement.pojo.*;
import com.ncepu.clubmanagement.pojo.inter.PermissionLevel;
import com.ncepu.clubmanagement.service.*;
import com.ncepu.clubmanagement.utils.PageDivideUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
public class AffairServiceImpl implements AffairService {

    @Autowired
    private AffairsMapper affairsMapper;

    @Autowired
    private ClubService clubService;

    @Autowired
    private UploadService uploadService;

    @Autowired
    private MultiMediaService multiMediaService;


    @Autowired
    private MessageService messageService;

    @Override
    @Transactional
    public AffairWithUrlResource addAffairPrev(Map<String, MultipartFile> file, Affair affair) throws Exception {

        // TODO: 修改使之能够接受和处理多URL情况，并且想办法区分文件类型！

        List<String> urls = new ArrayList<String>();

        // 预处理(只有部分添加事务的需要预处理，集中写在这里，便于集中管理预处理逻辑)
        if (affair.getBigAffairType().equals(Affair.COMMITTEE_TYPE) ||
        affair.getAffairType().equals(Affair.COMMITTEE_MODIFY_CLUB)) {
            // 这是修改社团类型的预处理：
            // 判断是否存在图片
            if (file != null && file.get("image") != null && !file.get("image").isEmpty()) {
                // 有图片就调用其它服务将图片上传阿里云OSS并保存至数据库
                MultipartFile image = file.get("image");
                // TODO: 完善相应服务，并在此处调用
                String image_url = uploadService.uploadFileWithRecord(Integer.toString(affair.getBigAffairType()) + affair.getClubId(),
                        "affair", image, "affair");
                urls.add(image_url);

                // 保存图片url
                affair.setValue5(image_url);
            }
        }
        // 预处理逻辑2：针对增加多媒体的预处理
        else if(affair.getBigAffairType().equals(Affair.CLUB_TYPE) &&
        affair.getAffairType().equals(Affair.CLUB_ADD_MULTIMEDIA)){
            // TODO: 完善相应服务，并在此处调用
            // 判空逻辑
            if(file == null || file.get("cover") == null || file.get("multimedia") == null ||
            file.get("cover").isEmpty() || file.get("multimedia").isEmpty()){
                throw new NotExistException("传输错误：漏传参数");

            }
            String cover_url = uploadService.uploadFileWithRecord(Integer.toString(affair.getBigAffairType()) + affair.getClubId(),
                    "affair", file.get("cover"), "affair");
            String multimedia_url = uploadService.uploadFileWithRecord(Integer.toString(affair.getBigAffairType()) + affair.getClubId(),
                    "affair", file.get("multimedia"), "affair");
            urls.add(cover_url);
            urls.add(multimedia_url);

            // 保存相应的url
            affair.setValue4(multimedia_url);
            affair.setValue5(cover_url);

        }
        //预处理逻辑3：针对修改多媒体的预处理
        else if(affair.getBigAffairType().equals(Affair.CLUB_TYPE) &&
                affair.getAffairType().equals(Affair.CLUB_MODIFY_MULTIMEDIA)) {
            // 判空与设置：
            if(file != null &&  file.get("cover") != null && ! file.get("cover").isEmpty()){
                // 第一个的url不为空，证明要修改封面
                String cover_url = uploadService.uploadFileWithRecord(Integer.toString(affair.getBigAffairType()) + affair.getClubId(),
                        "affair", file.get("cover"), "affair");
                urls.add(cover_url);
                // 保存相应url
                affair.setValue5(cover_url);
            }
            if(file != null &&  file.get("multimedia") != null && ! file.get("multimedia").isEmpty()){
                // 第二个的url不为空，证明要修改多媒体资源
                String multimedia_url = uploadService.uploadFileWithRecord(Integer.toString(affair.getBigAffairType()) + affair.getClubId(),
                        "affair", file.get("multimedia"), "affair");
                urls.add(multimedia_url);
                // 保存相应url
                affair.setValue4(multimedia_url);
            }

            // 信息补充逻辑：文章事务中需要根据多媒体资源获取到社团id
            Integer file_id = affair.getValue6();
            if(file_id == null) {
                throw new NotExistException("传输错误：漏传参数");
            }

            affair.setClubId(multiMediaService.getClubIdByMultiMediaId(file_id));


        }


        return new AffairWithUrlResource(affair,urls);
    }

    @Override
    public AffairContent getAffairContent(Integer id, Integer permission) throws NotExistException {

        Affair affair;

        // 权限判断
        if(PermissionLevel.isCommittee(permission)){
            affair = affairsMapper.getAffairByIdAndBigType(id, Affair.COMMITTEE_TYPE);
        }
        else{
            affair = affairsMapper.getAffairByIdAndBigType(id, Affair.CLUB_TYPE);
        }
        if(affair == null){
            throw new NotExistException();
        }

        AffairContent affairContent = AffairContent.createByAffair(affair);


        return affairContent;
    }


    @Transactional
    @Override
    public void addAffair(Map<String,MultipartFile> files, Affair affair) throws Exception {


        // 预处理(只有部分添加事务的需要预处理，集中写在这里，便于集中管理预处理逻辑)
        AffairWithUrlResource affairWithUrlResource = addAffairPrev(files, affair);
        affair = affairWithUrlResource.getAffair();
        // 预处理后的可能的图片资源
        List<String> urls = affairWithUrlResource.getUrls();

        // 事务本身合法性检查
        addAffairCheck(affair);

        if (affair.getBigAffairType().equals(Affair.COMMITTEE_TYPE)) {
            // 如果是事务大类型选项1，则执行相关操作
            affairsMapper.addCommitteeAffair(affair);

        } else if (affair.getBigAffairType().equals(Affair.CLUB_TYPE)) {
            // 如果是事务大类型选项2，则执行相关操作
            affairsMapper.addClubAffair(affair);
        }

        // 最终补充处理(确保url资源使用在最后设置)
        uploadService.setUrlResourceUsed(urls);

    }

    private void addAffairCheck(Affair affair) throws Exception {
        if(!affair.isAffairLegal()){  // 事务本身格式是否合法
            throw new Exception("传输错误：漏传参数");
        }
        // 特定逻辑下事务的合法性审查
        if (affair.getBigAffairType().equals(Affair.CLUB_TYPE) &&
        affair.getAffairType().equals(Affair.CLUB_ADD_PERSON)){
            // 社团添加成员事务的特定逻辑审查(加入时本身不能已经属于这个社团)
            if(clubService.isJoinedOrManaged(affair.getInitiatorId(), affair.getClubId())){
                throw new AlreadyExistException();
            }
        } else if (affair.getBigAffairType().equals(Affair.CLUB_TYPE) &&
        affair.getAffairType().equals(Affair.CLUB_REMOVE_PERSON)){
            // 社团移除成员事务的特定逻辑审查（移除时本身必须属于这个社团）
            if(!clubService.isJoined(affair.getInitiatorId(), affair.getClubId())) {
                throw new NotExistException();
            }
        } else if (affair.getBigAffairType().equals(Affair.CLUB_TYPE) &&
                    affair.getAffairType().equals(Affair.CLUB_MODIFY_MULTIMEDIA)){
            // 修改多媒体时需要保证同时传入/不传入type和multimedia_id
            if(Objects.isNull(affair.getValue3()) ^ StringUtil.isEmpty(affair.getValue4()) ){
                throw new NotExistException("传输错误：漏传参数");
            }

        }

    }


    @Override
    public PageBean getAffair(Integer type, Integer permission, Integer page,Integer pageSize, Integer personId) {

        List<AffairFont> ls;

        List<Integer> clubIds = clubService.getManagedClubIdWithoutPage(null, personId);

        // 使用PageDivideUtilAssist工具类封装分页逻辑，简化代码
        PageBean pageBean = PageDivideUtil.toPageBean(() -> {
            if (PermissionLevel.isCommittee(permission))
                // 是团委级别权限
                return getCommitteeAffair(type);
            else
                // 普通的权限
                // 首先根据id判定这个人的管理的社团id
            {
                return getClubAffairByClubIds(type,clubIds);
            }

        }, page, pageSize);

//        // 查询权限
//        if (PermissionLevel.isCommittee(permission)){
//            // 是团委级别权限
//            PageHelper.startPage(page, pageSize);
//            ls = this.getCommitteeAffair(type);
//        }
//        else {
//            // 普通的权限
//            PageHelper.startPage(page, pageSize);
//            ls = this.getClubAffair(type);
//        }
//
//            Page<AffairFont> p = (Page<AffairFont>)ls;
//            PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
            return pageBean;

    }

    @Override
    @Transactional
    public boolean handlePassedAffair(Integer id, Integer permission) throws Exception {
        // 获取具体事务
        Affair affair;
        if (PermissionLevel.isCommittee(permission)){
            // 如果是事务大类型选项1，则执行相关操作
            affair = this.getPassedCommitteeAffair(id);
        }
        else
            affair = this.getPassedClubAffair(id);

        // 没有事务查到的处理
        if (affair == null) {
            log.info("事务不存在");
            return false;
        }

        // 删除该事务
        affairsMapper.deleteAffairByIdAndBigType(id, affair.getBigAffairType());

        // 事务逻辑1- 团委级别添加社团
        if(affair.getBigAffairType().equals(Affair.COMMITTEE_TYPE)
                && affair.getAffairType().equals(Affair.COMMITTEE_ADD_CLUB)){
            // 创建clubAdd对象并调用相应服务添加
            ClubAdd clubAdd = new ClubAdd(affair.getValue1(),affair.getValue4(),affair.getValue3(),affair.getInitiatorId());
            clubService.addClub(clubAdd);
        }
        // 事务逻辑2- 请求添加社团成员
        else if(affair.getBigAffairType().equals(Affair.CLUB_TYPE)
                && affair.getAffairType().equals(Affair.CLUB_ADD_PERSON)){
            clubService.addPersonToClub(new ClubSelection(affair.getClubId(), affair.getInitiatorId()));
        }
        // 事务逻辑3- 请求移除社团成员
        else if(affair.getBigAffairType().equals(Affair.CLUB_TYPE)
                && affair.getAffairType().equals(Affair.CLUB_REMOVE_PERSON)){
            clubService.removePersonFromClub(new ClubSelection(affair.getClubId(), affair.getInitiatorId()));
        }
        // 事务处理逻辑4- 请求修改社团信息
        else if (affair.getBigAffairType().equals(Affair.COMMITTEE_TYPE)
                && affair.getAffairType().equals(Affair.COMMITTEE_MODIFY_CLUB)) {
            // 调用其它服务完成

            ClubModify clubModify = new ClubModify(affair.getClubId(),
            affair.getValue1(),affair.getValue4(),affair.getValue6(),affair.getValue5()
            ,affair.getValue3(),affair.getValue2());

            clubService.updateClubInfoByURL(clubModify);

        }
        // 事务处理逻辑5- 请求添加多媒体资源
        else if(affair.getBigAffairType().equals(Affair.CLUB_TYPE)
                && affair.getAffairType().equals(Affair.CLUB_ADD_MULTIMEDIA)){
            // 社团上传多媒体资源事务的处理逻辑
            MultiMediaFontOfAdd mediaFontOfAdd = new MultiMediaFontOfAdd(
                    affair.getClubId(), affair.getInitiatorId(), affair.getValue1(),
                    affair.getValue5(), affair.getValue4(), affair.getValue3());

            // 执行加入逻辑
            multiMediaService.addMultiMedia(mediaFontOfAdd);

        }
        // 事务处理逻辑6- 请求修改多媒体资源
        else if(affair.getBigAffairType().equals(Affair.CLUB_TYPE)
                && affair.getAffairType().equals(Affair.CLUB_MODIFY_MULTIMEDIA)) {
            // 社团修改多媒体资源事务的处理逻辑
            MultiMediaChangeableInfo mediaChangeableInfo = new MultiMediaChangeableInfo(
                    affair.getValue6(), affair.getValue2(), affair.getValue1(),
                    affair.getValue5(), affair.getValue4(), affair.getValue3());

            // 执行修改逻辑
            multiMediaService.updateMultiMedia(mediaChangeableInfo);

        }
        // TODO: 其它逻辑待补充


        else{
            log.info("事务逻辑未实现/请求了没有设计的事务");
            return false;
        }

        afterAffair(affair);

        // TODO: 部分事务的接受操作
        return true;
    }

    // 事务拒绝逻辑
    @Override
    @Transactional
    public boolean handleRejectAffair(Integer id, Integer permission) {

        // 获取具体事务
        Affair affair;
        if (PermissionLevel.isCommittee(permission)){
            // 如果是事务大类型选项1，则执行相关操作
            affair = this.getPassedCommitteeAffair(id);
        }
        else
            affair = this.getPassedClubAffair(id);

        // 没有事务查到的处理
        if (affair == null) {
            log.info("事务不存在");
            return false;
        }

        Integer bigType;
        // 权限判断
        if (PermissionLevel.isCommittee(permission)){
            bigType = Affair.COMMITTEE_TYPE;
        }
        else
            bigType = Affair.CLUB_TYPE;

        // 删除该事务
        affairsMapper.deleteAffairByIdAndBigType(id, bigType);
        // 部分逻辑需要补充（比如占用缓存的URL的释放等）
        // TODO: 部分事务的删除后补充操作
        afterAffair(affair);

        return true;
    }

    private void afterAffair(Affair affair){
        // 这个方法用于释放事务可能的资源（主要是URL）

        if (affair.getBigAffairType().equals(Affair.COMMITTEE_TYPE)
                && affair.getAffairType().equals(Affair.COMMITTEE_MODIFY_CLUB)){
            // 释放数据库的社团图片URL
            uploadService.releaseUrlResource(affair.getValue5());
        }
        else if(affair.getBigAffairType().equals(Affair.CLUB_TYPE)
                && (  affair.getAffairType().equals(Affair.CLUB_ADD_MULTIMEDIA)  ||
                affair.getAffairType().equals(Affair.CLUB_MODIFY_MULTIMEDIA)
        )){
            // 释放事务表url数据库的社团图片URL(对应两种情况：添加和修改多媒体资源)
            uploadService.releaseUrlResource(affair.getValue4());
            uploadService.releaseUrlResource(affair.getValue5());
        }
    }


    @CommitteePermission
    private List<AffairFont> getCommitteeAffair(Integer type){
        return affairsMapper.getCommitteeFontAffairByType(type);
    }

    private List<AffairFont> getClubAffair(Integer type){
        return affairsMapper.getClubFontAffairByType(type);
    }

    private List<AffairFont> getClubAffairByClubIds(Integer type, List<Integer> clubIds){
        return affairsMapper.getClubFontAffairByTypeAndClubId(type, clubIds);
    }

    @CommitteePermission
    private Affair getPassedCommitteeAffair(Integer id){
        return affairsMapper.getAffairByIdAndBigType(id, Affair.COMMITTEE_TYPE);
    }

    private Affair getPassedClubAffair(Integer id){

        return affairsMapper.getAffairByIdAndBigType(id, Affair.CLUB_TYPE);
    }
}
